package encodingSimulation;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.Iterator;

import testing.DecodingImplementation;

import decodingSimulaiton.DecodingHelper;
import decodingSimulaiton.DecodingImplementationVer2;

public class EncodingInitiator {
	// TODO check the code change for calculating the source fragments creation

	/**
	 * @param args
	 */
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		File filename = new File("C:" + File.separator + "Users"
				+ File.separator + "Bhavya" + File.separator + "Desktop"
				+ File.separator + "java_for_cloudcomputing" + File.separator
				+ "java_code" + File.separator + "Sample.doc.txt");
		File createdFilename = new File("C:" + File.separator + "Users"
				+ File.separator + "Bhavya" + File.separator + "Desktop"
				+ File.separator + "java_for_cloudcomputing" + File.separator
				+ "java_code" + File.separator + "ObtainedSampleOFG.doc.txt");
		//		File createdFilename2 = new File("C:" + File.separator + "Users"
		//				+ File.separator + "Bhavya" + File.separator + "Desktop"
		//				+ File.separator + "java_for_cloudcomputing" + File.separator
		//				+ "java_code" + File.separator + "ObtainedSampleNormal.doc.txt");

		// Reliability indicates the reliability with which to recover the file
		double Reliability = .999999999999;
		int numberOfSourceFragments = 128;
		double serverAvailabilityProbability = .9;
		/*
		 * optionforgenerator 1- pseudo random number generator 2- kent map
		 * generator
		 */
		int OPTIONFORGENERATOR = 1;
		//		ArrayList<BitSet> obtainedSourceFragments, obtainedSourceFragments2;
		int[][] generatorMatrix;
		ArrayList<BitSet> encodedFragments = new ArrayList<BitSet>();
		ArrayList<BitSet> sourceBits = new ArrayList<BitSet>();
		EncodingImplementation encoder = new EncodingImplementation();
		EncodingHelper eHelper = new EncodingHelper(encoder);
		String checksum1 = null, checksum2 = null;
		// Fragment size always in multiples of 256 or higher which defines the
		// fragment size

		/*
		 * Setting values of parameters *
		 */
		encoder.setFileName(filename);
		encoder.setReliability(Reliability);
		encoder.setNumberOfSourceFragments(numberOfSourceFragments);
		encoder.setServerAvailabilityProbability(serverAvailabilityProbability);

		/*
		 * Encoder call
		 */
		long time1 = System.nanoTime();
		sourceBits = eHelper.fragmentSourceData(filename);
		generatorMatrix = eHelper.createGeneratorMatrix(OPTIONFORGENERATOR);
		/*
		 * Encoding the bitset data set using the generator matrix
		 */
		encodedFragments = encoder.createEncodedPackets(sourceBits,
				generatorMatrix);
		long time2 = System.nanoTime();
		System.out.println(" encoding time");
		System.out.println(time2 - time1);
		sourceBits = null;
		/*
		 * Initiating Decoder operation
		 */
		time1 = time2 = 0;
		time1 = System.nanoTime();
		/*
		 * find transpose of generator matrix
		 */
		int k = encoder.getNumberOfSourceFragments();
		int N_new = encoder.getTotalEncodedPackets();
		DecodingHelper dHelper= new DecodingHelper(k, N_new);
		DecodingImplementationVer2 decoderVer2 = new DecodingImplementationVer2(k, N_new);
		int[][] generatorTranspose = dHelper.matrixTranspose(generatorMatrix);

		/*
		 * callDecodeOnTheFly -- takes into account the server availability
		 * before choosing the to obtain the encoded vector and the encoded
		 * fragment from the server
		 */

		int[] index = decoderVer2.onTheFlyServer(generatorTranspose,
				dHelper.identity(k));
		int[] serverAvailability = dHelper.serverAvailability();
		int canProceed = dHelper.gaussianElimination(generatorTranspose, index);
		int serverCount = k, currentServerCount = 0;

		if (canProceed == 1) {
			canProceed = 0;
			while (currentServerCount < serverCount) {
				for (int serverNumber : index) {
					System.out.println(" svrNbr" + serverNumber + ":"
							+ serverAvailability[serverNumber]);
					if (serverAvailability[serverNumber] == 1) {
						currentServerCount++;
					} else {
						/*
						 * find out another server in place of this missing
						 * server" serverNumber"
						 */
						currentServerCount = 0;
						index = decoderVer2.onNextSetOfServerVer2(generatorTranspose,
								serverNumber, dHelper.identity(k));
						System.out.println("Linearly independent"+dHelper.gaussianElimination(generatorTranspose, index));
						break;
					}
				}
			}
		}

		ArrayList<BitSet> obtainedSourceFragments=decoderVer2.decodePacketsVer2(encodedFragments, generatorTranspose, k, N_new, index);
		StringBuffer obtainedSource = new StringBuffer();
		Iterator<BitSet> iter2 = obtainedSourceFragments.iterator();
		while (iter2.hasNext()) {
			obtainedSource.append(new String(iter2.next().toByteArray()));
		}
		eHelper.writeToFile(createdFilename, obtainedSource.toString());
		try {
			checksum1 = eHelper.getMD5Checksum(filename);
			checksum2 = eHelper.getMD5Checksum(createdFilename);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (checksum1.equals(checksum2)) {

			System.out.println(" The checksum is the same(ofg); data equal");
		}else {
			System.out.println(" big big trouble");
		}

	}

}
